"""
首先要知道，pyqt5当中的组件分为容器组件和数据组件

然后引入MVC概念（Model-View-Controller） 这里Model：模型层。View：视图层。Controller：控制层
 我们一般是从这三层架构来设计GUI的程序。（这里要注意：人工智能的机器学习也可以使用这种设计思路）
  进一步理解：Model：简单理解为数据层。View：展现层。Controller：控制层。
    这里层和层的关系应该是松耦合的，也就是层和层的关系尽量是减少相关联，（优点是自由度高）

Model/View（模型/试图）结构是Qt中用界面组件显示与编辑数据的一种结构，
  视图（View）是显示和编辑数据的界面组件
  模型（Model）是视图与原始数据之间的接口

补充：python主要是对于数据的处理，以及图像上的处理，这是python比较强项的地方

GUI应用程序的一个很重要的功能是由用户在界面上编辑和修改数据，典型的如数据库应用程序。
数据库应用程序中，用户在界面上执行各种操作，实际上是修改了界面组件所关联的数据库信息。

将界面组件与所编辑的数据分离开来，又通过数据源的方式连接起来，是处理界面和数据的一种较好的方式。
Qt使用Model/View结构来处理这种关系

个人理解：Model/View这种架构的基本思想就是
    模型（model）先获取对应数据库中的相关数据-->
    模型（model）通过视图或视图组件来显示数据-->
    视图组件上通过代理机制对模型（model）中的数据进行修改-->
    模型（model）再通知数据库更改数据库当中的对应数据

    补充：代理机制--就是消息（信号）和槽（封装起来了）

具体来看的话
    数据（Data）是实际的数据，如数据库的一个数据表或者SQL查询结果，内存中的一个StringList，或磁盘文件结构等

    视图或者视图组件（View）是屏幕上的界面组件，视图从数据模型获取每个数据项的模型索引（model index），
    通过模型索引获取数据，然后为界面组件提供显示数据。Qt提供一些现成的数据视图组件，如QlistView（）、
    QTreeView和QTableView等。

    模型或者模型（model）与实际数据通信，并为视图组件提供数据接口。它从原始数据提取需要的内容，并为视图组件
    进行显示和编辑。Qt中有一些预定义的数据模型，如QStringListModel可作为StringList的数据模型，
    QsqlTableModel可以作为数据库中一个数据表的数据模型。

    理解：再次强调，model是一种中间介质，它成为了view和数据（数据库中）的桥梁和纽带。
        并且这里还需要注意，数据与model应该是匹配的，view和model是匹配的。
            数据    ---（匹配）---    model    ---（匹配）---    view

    在model/view结构当中，还提供了代理（Delegate）功能，代理功能可以让用户制定数据的界面显示和编辑方式。
    在标准的视图组件中，代理功能显示一个数据，当数据被编辑时，代理通过模型索引与数据模型通信，并为编辑数据
    提供一个编辑器，一般是一个QLineEdit组件
    理解：其实代理就是 信号和槽功能
        而这里的代理就是，qt提供了一个可编辑界面，默认提供的就是QLineEdit组件，
        也就是可以实现对界面数据的操作可以同步到数据库，另外注意！这里的编辑是指 update操作，也就是修改数据的操作。
        而insert和delete不叫编辑。

    模型、视图和代理之间使用模型和槽通信。
    当源数据发生变化时，数据模型发射信号通知视图组件；
    当用户在界面上的操作数据时，视图组件发射信号表示这些操作信息；
    当编辑数据时，代理发射信号告知数据模型和视图组件编辑器的状态

    Qt当中事件处理的核心就是 信号和槽机制
"""

#################################################################################
# FileDir 磁盘路径 #
# 通过Qt显示出磁盘的路径。
from os.path import expanduser  # 这是为了获取系统路径  expanduser：就是当前路径的图形
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

def FileDir_view_model():
    # 获取路径信息
    home_directory = expanduser('~')     # 获取家目录，对于Linux来说就是用户目录
    # 构建QT程序
    #   首先构建app(程序控制)
    app = QApplication([])    # [] 表示启动程序时不需要参数
    # 为了将磁盘的路径显示出来，那么我们需要一个treeview
    view = QTreeView()
    # 还需要模型model
    model = QDirModel()    # 不同的数据需要不同的model，不同的view需要不同的model
    # 将view和model进行连接
    view.setModel(model)
    # 并且model当中还需要有数据，也就是需要将数据添加进model当中(当然有的时候model默认就含有data)
    # 这里的QDirModel()默认数据是全磁盘的文件结构，而如果我们只需要指定磁盘的路径，那就需要特殊绑定
    view.setRootIndex(model.index(home_directory))   # 将视图的根索引设置成模型当中的home_directory
    # 窗口显示
    view.show()
    # 程序执行
    app.exec_()


# 函数调用
# FileDir_view_model()
###################################################################################
# 做一个StringList的model
# 也就是将字符串显示在界面当中
def qstringmodel():
    app = QApplication([])
    view = QListView()
    model = QStringListModel(['zhangsan', 'lisi', 'Bob'])
    view.setModel(model)
    view.show()
    app.exec_()


# qstringmodel()
####################################################################################
"""
常见视图组件：
            QListView：用于显示单列表格数据，适用于一维数据的操作
            QTreeView：用于显示梳妆结构数据，适用于树状结构数据的操作
            QTableView：用于显示表格状数据，适用于二维表格型数据的操作
            QColumnView：用于多个QListView显示树状结构层次结构，树状结构的一层用一个QLisView显示
            QHeaderView：提供行表头或列表头的视图组件，如QTableView的行表头和列表头
            
            # 以下是常用的view
            QListView -- > QListWidget
            QTableView -- > QTableWidget
            QTreeView --> QTreeWidget
            QColumnView
            QHeaderView
            以上的视图的父类是：QAbstractItemView（抽象类视图）
                            也就是说明它们不能直接完成实际的事情，所以需要使用对应的具体组件
            也就是所有的基于项数据模型（Model）都是基于QAbstractItemModel类的，这个类定义了视图组件和
            代理存储数据的接口。数据无需存储在数据模型里，数据可以是其他类、文件、数据库或者任何数据源。
            
            # 以下是常用的model
            QStringListModel --> 用于处理字符串列表的数据模型类
            QStandardItemModel --> 标准的基于项数据的数据模型类，每个项数据可以是任何数据类型
            QFileSy sternModel --> 计算机上文件系统的数据模型类
            QSortFilterProxyModel --> 与其他数据模型结合，提供排序和过滤功能的数据模型类
            QSqlQueryModel --> 用于数据库sql查询结果的数据模型类
            QSqlTableModel --> 用于数据库的一个数据表的数据模型类
            QSqlRelationalTableModel --> 用于关系型数据表的数据模型类
            
            再次强调，抽象的类都不能直接使用，需要定义一个子类，在继承父类（抽象类）的基础上
            需要定义或者重写一些方法，来达到最终的模型效果
            
"""

#####################################################################################
# 接下来我们将通过QTableView model的学习来了解QT当中的 model/view模型
# tableview的优点：与数据库绑定。